﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using TabbedTemplate.Models;

namespace TabbedTemplate.Services
{
    public class StoreService : IStoreService
    {
        //******** 共有变量
        /// <summary>
        /// 一页返回数量。
        /// </summary>
        public const int PageSize = 10;

        //******** 私有变量
        /// <summary>
        /// 从web获取的店铺数据
        /// </summary>
        private List<Store> _storesFromWeb;

        //******** 私有常量
        /// <summary>
        /// 百度地图AK
        /// </summary>
        private const string BaiduAK = "qj44X3tjKlOpqmORGXCfzMfdNMhhnS0G";

        private IPreferenceStorage _preferenceStorage;

        private ILocationService _locationService;

        private Position currentPosition;

        //******** 构造函数
        public StoreService(IPreferenceStorage preferenceStorage,
            ILocationService locationService)
        {
            _preferenceStorage = preferenceStorage;
            _locationService = locationService;


        }


        /// <summary>
        /// 从Web服务获取店铺信息
        /// </summary>
        /// <returns></returns>
        ///<param name="tag">例如中餐</param>//枚举
        /// <param name="location">位置的坐标</param>
        /// <param name="radius">圆的半径</param>
        /// <param name="PageNum">页码</param>

        // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse); 
        public class Location
        {
            public double lat { get; set; }
            public double lng { get; set; }
        }

        public class NaviLocation
        {
            public double lng { get; set; }
            public double lat { get; set; }
        }

        public class DetailInfo
        {
            public string distance { get; set; }
            public string tag { get; set; }
            public string type { get; set; }
            public string detail_url { get; set; }
        }

        public class Result
        {
            public string name { get; set; }
            public Location location { get; set; }
            public string address { get; set; }
            public string city { get; set; }
            public string area { get; set; }
            public string uid { get; set; }
            public DetailInfo detail_info { get; set; }
            public string telephone { get; set; }
        }

        public class Root
        {
            public List<Result> results { get; set; }
        }


        public async Task<List<Store>> GetStoresFromWebAsync(Tag tag,
            double lat, double lng, int radius, int PageNum)
        {
            string location = lat + "," + lng;
            string localTag = tag.CnName;
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();
            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=美食&tag=" +
                    localTag + "&location=" + location + "&radius=" + radius +
                    "&page_size=" + PageSize + "&page_num=" + PageNum +
                    "&scope=2&output=json&ak=" + BaiduAK +
                    "&filter=industry_type:cater|sort_name:distance|sort_rule:1&city_limit=true");
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();

            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);

            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance =
                    Convert.ToString(Convert.ToDouble(p.detail_info.distance) /
                        1000),
                Tag = p.detail_info.tag
            }).ToList();
            //var i = new double[] { 0, 0, 0 };
            //var j = i.Select(p => (int)p).ToArray();
            return _storesFromWeb;
        }


        public async Task<List<Store>> SearchStoresByNameFromWebAsync(
            string tag, double lat, double lng, int radius, int PageNum)
        {
            string location = lat + "," + lng;
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();
            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=美食&tag=" +
                    tag + "&location=" + location + "&radius=" + radius +
                    "&page_size=" + PageSize + "&page_num=" + PageNum +
                    "&filter=industry_type:cater|sort_name:distance|sort_rule:1&scope=2&output=json&ak=" + BaiduAK);
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();

            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);

            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance =
                    Convert.ToString(Convert.ToDouble(p.detail_info.distance) /
                        1000),
                Tag = p.detail_info.tag
            }).ToList();
            return _storesFromWeb;
        }

        /// <summary>
        /// 根据城市名获取店铺。
        /// 当前选择城市与定位城市不一致时调用。除开北京市。
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="cityName"></param>
        /// <param name="PageNum"></param>
        /// <returns></returns>
        public async Task<List<Store>> GetStoresFromWebByRegionAsync(string tag,
            string cityName, int PageNum)
        {
            var currentLocationLatitude =
                _preferenceStorage.Get("currentLocationLatitude", 39.915);
            var currentLocationLongitude =
                _preferenceStorage.Get("currentLocationLongitude", 116.404);
            currentPosition = new Position
            {
                Latitude = currentLocationLatitude,
                Longitude = currentLocationLongitude
            };
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();
            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=美食&tag=" +
                    tag + "&region=" + cityName + "&page_size=" + PageSize +
                    "&page_num=" + PageNum + "&scope=2&output=json&ak=" +
                    BaiduAK +
                    "&filter=industry_type:cater|sort_name:distance|sort_rule:1&city_limit=true");
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();

            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);

            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance = p.detail_info.distance ??
                    _locationService.CalculateDistance(currentPosition,
                        new Position
                        {
                            Latitude = p.location.lat,
                            Longitude = p.location.lng
                        }),
                Tag = p.detail_info.tag
            }).ToList();
            return _storesFromWeb;
        }

        /// <summary>
        /// 全局搜索。
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="cityName"></param>
        /// <param name="PageNum"></param>
        /// <returns></returns>
        public async Task<List<Store>> SearchStoresByRegionFromWebAsync(
            string tag, string cityName, int PageNum)
        {
            var currentLocationLatitude =
                _preferenceStorage.Get("currentLocationLatitude", 39.915);
            var currentLocationLongitude =
                _preferenceStorage.Get("currentLocationLongitude", 116.404);
            currentPosition = new Position
            {
                Latitude = currentLocationLatitude,
                Longitude = currentLocationLongitude
            };
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();

            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=" +
                    tag + "&region=" + cityName + "&page_size=" + PageSize +
                    "&page_num=" + PageNum + "&scope=2&output=json&ak=" +
                    BaiduAK +
                    "&city_limit=true&filter=industry_type:cater|sort_name:distance|sort_rule:1&radius=10000");
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();
            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);
            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance = p.detail_info.distance ??
                    _locationService.CalculateDistance(currentPosition,
                        new Position
                        {
                            Latitude = p.location.lat,
                            Longitude = p.location.lng
                        }),
                Tag = p.detail_info.tag
            }).ToList();
            return _storesFromWeb;
        }

        public async Task<List<Store>> SearchStoresByRegionClassifyFromWebAsync(
            string tag, string query, string cityName, int PageNum)
        {
            var currentLocationLatitude =
                _preferenceStorage.Get("currentLocationLatitude", 39.915);
            var currentLocationLongitude =
                _preferenceStorage.Get("currentLocationLongitude", 116.404);
            currentPosition = new Position
            {
                Latitude = currentLocationLatitude,
                Longitude = currentLocationLongitude
            };
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();

            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=" +
                    query + "&tag=" + tag + "&region=" + cityName + "&page_size=" + PageSize +
                    "&page_num=" + PageNum + "&scope=2&output=json&ak=" +
                    BaiduAK +
                    "&city_limit=true&filter=sort_name:distance|sort_rule:1&radius=1000000");
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();
            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);
            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance = p.detail_info.distance ??
                      _locationService.CalculateDistance(currentPosition,
                          new Position
                          {
                              Latitude = p.location.lat,
                              Longitude = p.location.lng
                          }),
                Tag = p.detail_info.tag
            }).ToList();
            return _storesFromWeb;
        }

        public async Task<List<Store>> GetHotStoresFromWebAsync(string cityName)
        {
            var currentLocationLatitude =
                _preferenceStorage.Get("currentLocationLatitude", 39.915);
            var currentLocationLongitude =
                _preferenceStorage.Get("currentLocationLongitude", 116.404);
            currentPosition = new Position
            {
                Latitude = currentLocationLatitude,
                Longitude = currentLocationLongitude
            };
            _storesFromWeb = new List<Store>();
            using var httpClient = new HttpClient();

            HttpResponseMessage response;
            try
            {
                response = await httpClient.GetAsync(
                    "http://api.map.baidu.com/place/v2/search?query=美食&region=" + cityName + "&scope=2&filter=industry_type:cater|sort_name:overall_rating|sort_rule:0&output=json&ak=qj44X3tjKlOpqmORGXCfzMfdNMhhnS0G");
                response.EnsureSuccessStatusCode();
            }
            catch (Exception e)
            {
                throw e;
            }

            var json = await response.Content.ReadAsStringAsync();
            var StoreSentence = JsonConvert.DeserializeObject<Root>(json);
            _storesFromWeb = StoreSentence.results.Select(p => new Store
            {
                Uid = p.uid,
                Name = p.name,
                Address = p.address,
                Area = p.area,
                Telephone = p.telephone ?? "暂无",
                Distance = p.detail_info.distance ??
                    _locationService.CalculateDistance(currentPosition,
                        new Position
                        {
                            Latitude = p.location.lat,
                            Longitude = p.location.lng
                        }),
                Tag = p.detail_info.tag
            }).ToList();
            return _storesFromWeb;
        }
    }

    /// <summary>
    /// 二级分类
    /// </summary>
    public class Tag
    {
        /// <summary>
        /// 中文名
        /// </summary>
        public string CnName { get; }

        /// <summary>
        /// 英文名
        /// </summary>
        public string EnName { get; }

        public Tag(string cnName, string enName)
        {
            CnName = cnName;
            EnName = enName;
        }

        /// <summary>
        /// 中餐厅
        /// </summary>
        public static readonly Tag ChineseRestuarant =
            new Tag("中餐厅", nameof(ChineseRestuarant));

        public static readonly Tag ForeignRestuarant =
            new Tag("外国餐厅", nameof(ForeignRestuarant));

        public static readonly Tag FastRestuarant =
            new Tag("小吃快餐店", nameof(FastRestuarant));

        public static readonly Tag CakeAndDesert =
            new Tag("蛋糕甜品店", nameof(CakeAndDesert));

        public static readonly Tag Cafe = new Tag("咖啡厅", nameof(Cafe));
        public static readonly Tag Tea = new Tag("茶座", nameof(Tea));
        public static readonly Tag Bar = new Tag("酒吧", nameof(Bar));
        public static readonly Tag Buffet = new Tag("自助餐", nameof(Buffet));

        public static readonly Tag OnlyForAdmin =
            new Tag("", nameof(OnlyForAdmin));
    }
}
